home *** CD-ROM | disk | FTP | other *** search
/ QRZ! Ham Radio 1 / QRZ Ham Radio Callsign Database - December 1993.iso / ucsd / packet / tcpip / amiga / asrc29k.lha / wildmat.c < prev   
Encoding:
C/C++ Source or Header  |  1993-01-08  |  4.1 KB  |  162 lines

  1.  
  2. /*
  3.  * @(#)wildmat.c 1.3 87/11/06    Public Domain.
  4.  *
  5. From: rs@mirror.TMC.COM (Rich Salz)
  6. Newsgroups: net.sources
  7. Subject: Small shell-style pattern matcher
  8. Message-ID: <596@mirror.TMC.COM>
  9. Date: 27 Nov 86 00:06:40 GMT
  10.  
  11. There have been several regular-expression subroutines and one or two
  12. filename-globbing routines in mod.sources.  They handle lots of
  13. complicated patterns.  This small piece of code handles the *?[]\
  14. wildcard characters the way the standard Unix(tm) shells do, with the
  15. addition that "[^.....]" is an inverse character class -- it matches
  16. any character not in the range ".....".  Read the comments for more
  17. info.
  18.  
  19. For my application, I had first ripped off a copy of the "glob" routine
  20. from within the find(1) source, but that code is bad news:  it recurses
  21. on every character in the pattern.  I'm putting this replacement in the
  22. public domain.  It's small, tight, and iterative.  Compile with -DTEST
  23. to get a test driver.  After you're convinced it works, install in
  24. whatever way is appropriate for you.
  25.  
  26. I would like to hear of bugs, but am not interested in additions; if I
  27. were, I'd use the code I mentioned above.
  28. */
  29. /*
  30. **  Do shell-style pattern matching for ?, \, [], and * characters.
  31. **  Might not be robust in face of malformed patterns; e.g., "foo[a-"
  32. **  could cause a segmentation violation.
  33. **
  34. **  Written by Rich $alz, mirror!rs, Wed Nov 26 19:03:17 EST 1986.
  35. */
  36.  
  37. /*
  38.  * Modified 6Nov87 by John Gilmore (hoptoad!gnu) to return a "match"
  39.  * if the pattern is immediately followed by a "/", as well as \0.
  40.  * This matches what "tar" does for matching whole subdirectories.
  41.  *
  42.  * The "*" code could be sped up by only recursing one level instead
  43.  * of two for each trial pattern, perhaps, and not recursing at all
  44.  * if a literal match of the next 2 chars would fail.
  45.  */
  46.  
  47. /* Modified by Anders Klemets to take an array of pointers as an optional
  48.    argument. Each part of the string that matches '*' is returned as a
  49.    null-terminated, malloced string in this array.
  50.  */
  51. #include "global.h"
  52. static int Star __ARGS((char *s,char *p,char **argv));
  53. #define FALSE    0
  54. #define TRUE    1
  55.  
  56. static int
  57. Star(s,p,argv)
  58. register char *s;
  59. register char *p;
  60. register char **argv;
  61. {
  62.     char *cp = s;
  63.     while (wildmat(cp, p, argv) == FALSE)
  64.         if(*++cp == '\0')
  65.             return -1;
  66.     return cp - s;
  67. }
  68.  
  69. int
  70. wildmat(s,p,argv)
  71. register char *s;
  72. register char *p;
  73. register char **argv;
  74. {
  75.     register int last;
  76.     register int matched;
  77.     register int reverse;
  78.     register int cnt;
  79.  
  80.     for(; *p; s++,p++){
  81.         switch(*p){
  82.         case '\\':
  83.             /* Literal match with following character; fall through. */
  84.             p++;
  85.         default:
  86.             if(*s != *p)
  87.                 return FALSE;
  88.             continue;
  89.         case '?':
  90.             /* Match anything. */
  91.             if(*s == '\0')
  92.                 return FALSE;
  93.             continue;
  94.         case '*':
  95.             /* Trailing star matches everything. */
  96.             if(argv == NULLCHARP)
  97.                 return *++p ? 1 + Star(s, p, NULLCHARP) : TRUE;
  98.             if(*++p == '\0'){
  99.                 cnt = strlen(s);
  100.             } else {
  101.                 if((cnt = Star(s, p, argv+1)) == -1)
  102.                     return FALSE;
  103.             }
  104.             *argv = mallocw(cnt+1);
  105.             strncpy(*argv,s,cnt);
  106.             *(*argv + cnt) = '\0';
  107.             return TRUE;
  108.         case '[':
  109.             /* [^....] means inverse character class. */
  110.             reverse = (p[1] == '^') ? TRUE : FALSE;
  111.             if(reverse)
  112.                 p++;
  113.             for(last = 0400, matched = FALSE; *++p && *p != ']'; last = *p){
  114.                 /* This next line requires a good C compiler. */
  115.                 if(*p == '-' ? *s <= *++p && *s >= last : *s == *p)
  116.                     matched = TRUE;
  117.             }
  118.             if(matched == reverse)
  119.                 return FALSE;
  120.             continue;
  121.         }
  122.     }
  123.     /* For "tar" use, matches that end at a slash also work. --hoptoad!gnu */
  124.     return *s == '\0' || *s == '/';
  125. }
  126.  
  127.  
  128. #ifdef    TEST
  129. #include <stdio.h>
  130.  
  131. extern char *gets();
  132.  
  133. main()
  134. {
  135.     char pattern[80];
  136.     char text[80];
  137.     char *argv[80], *cp;
  138.     int cnt;
  139.     
  140.     while (TRUE){
  141.         printf("Enter pattern:  ");
  142.         if(gets(pattern) == NULL)
  143.             break;
  144.         while (TRUE){
  145.             bzero(argv,80*sizeof(char *));
  146.             printf("Enter text:  ");
  147.             if(gets(text) == NULL)
  148.                 exit(0);
  149.             if(text[0] == '\0')
  150.                 /* Blank line; go back and get a new pattern. */
  151.                 break;
  152.             printf("      %d\n", wildmat(text, pattern, argv));
  153.             for(cnt = 0; argv[cnt] != NULLCHAR; ++cnt){
  154.                 printf("String %d is: '%s'\n",cnt,argv[cnt]);
  155.                 free(argv[cnt]);
  156.             }
  157.         }
  158.     }
  159.     exit(0);
  160. }
  161. #endif    /* TEST */
  162.